package com.big_data_studio.fiter;

import com.big_data_studio.exception.CustomException;
import com.big_data_studio.entity.user.UserDetailsModel;
import com.big_data_studio.util.general.RedisUtil;
import com.big_data_studio.util.general.TokenUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collection;
import java.util.Objects;


/**
 * @author xiao_jie
 * @date 2022/10/6 15:12
 * @describe   所要请求前必须要执行的方法
 */

@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private TokenUtil tokenUtil1;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (Objects.equals(request.getRequestURI(), "/user/login")){
            filterChain.doFilter(request,response);
            return;
        }
        String token = request.getHeader("token");
        //token认证
        if (Objects.equals(token, "null") || Objects.isNull(token)){
            filterChain.doFilter(request,response);   //  放行,没有进行用户身份信息认证
            return;
        }
        // 判断token的合法性  （判断签名是否合法）
        Claims claims = tokenUtil1.parseJWT(token);
        if (Objects.isNull(claims)){      //token解析失败
            throw new CustomException(403,"token无效！！");
        }
        //合法toke
        String uuid = claims.getSubject();
        // 判断token是否过期和是否是最新生成的
        if (uuid!=null && tokenUtil1.isTokenExpired(token) && tokenUtil1.isNewToken(uuid,token)){
            UserDetailsModel userDetailsModel =(UserDetailsModel) redisUtil.get(uuid);
            assert userDetailsModel!=null;  //断言用户信息不为空
            Collection<? extends GrantedAuthority> authorities = userDetailsModel.getAuthorities();//用户权限
            //将认证结果封装到认证实例对象，保存到SpringSecurity容器
            UsernamePasswordAuthenticationToken authenticationToken=
                    new UsernamePasswordAuthenticationToken(userDetailsModel,uuid,authorities);
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }else {
            redisUtil.del(uuid);
            tokenUtil1.deleteToken(uuid);
            throw new CustomException(403,"token已经过期！！");
        }
        filterChain.doFilter(request,response);
    }

}
